#pragma once
#include <string>
#include <json/json.h>
#include <boost/shared_ptr.hpp>
#include <vector>

namespace dataGrabber
{
	// abstracting the logger so that we can replace it with any other at a later stage
	// TODO
	/*class LOGGER
	{
	public:
		static void debug(std::string)
		static void warn(std::string)
		static void error(std::string)
	}; */

	class IGenericObject
	{
	public:
		virtual std::string id()=0;
		virtual std::string displayName()=0;
		virtual bool hasAttribute(std::string name)=0;
		virtual Json::Value getAttribute(std::string name, Json::Value jsonDefaultValue)=0;
		virtual Json::Value::iterator getAttributes() =0;
		virtual std::string toString()=0;
		virtual Json::Value toJson()=0;

		// having to implement a setter is optional
		virtual void setAttribute(std::string name, Json::Value & jsonValue)
		{
			// INTENTIONAL - no implementation by purpose
		}
	};

	class ISupportPositionInfo : public IAmGenericObject
	{
	public:
		// (left,top)
		virtual std::pair<double,double> getPosition() = 0;
		// (width,height)
		virtual std::pair<double,double> getSize() = 0;
	};

	class ILayoutAwareObject : public ISupportPositionInfo
	{
	public:
		
		virtual boost::shared_ptr<IAmLayoutAwareObject> neighbor_left() = 0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> neighbor_right() = 0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> neighbor_top() = 0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> neighbor_down() = 0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> selectLayoutObjectByXPath(std::string xpath)=0;
	};

	class ILayoutObjectCollection : std::vector<boost::shared_ptr<IAmLayoutAwareObject>>
	{

	public:
		// additional colleciton level api's comes here
	};


	// A document is a collection of layout-aware object
	class IDocument
	{
	public:
		virtual void initialize()	=0; 
		virtual void unInitialize() = 0;
		virtual boost::shared_ptr<ILayoutObjectCollection> getElements()=0;
		/* additional document level api */
	};

	//------------------------  data grabbar object model starts here -------------------------//
	class IDocumentProvider
	{
	public:
		virtual void initialize()	=0; 
		virtual void unInitialize() = 0;
		virtual boost::shared_ptr<IDocument> fetch() = 0;
	};

	typedef enum
	{
		st_integer_number,
		st_real_number,
		st_string,
		st_phoneNumber,
		st_currency,
		st_zipCode,
		st_emailAddress
	} standardElementType;

	class ISupportDataGrabApi
	{
	public:
		virtual void initialize( boost::shared_ptr<IDocument> targetDocument ) = 0;
		virtual void unInitialize() = 0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> findFirst(std::string labelRegExpression, standardElementType elementType)=0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> findFirst(std::string labelRegExpression, std::string typeRegExpression)=0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> findLast(std::string labelRegExpression, standardElementType elementType)=0;
		virtual boost::shared_ptr<IAmLayoutAwareObject> findLast(std::string labelRegExpression, std::string typeRegExpression)=0;
		virtual boost::shared_ptr<ILayoutObjectCollection> findCollection(std::string labelRegExpression, standardElementType elementType)=0;
		virtual boost::shared_ptr<ILayoutObjectCollection> findCollection(std::string labelRegExpression, std::string typeRegExpression)=0;
		
	};




}